<?php
/*
* 视频扩展类, 该类主要用于下载视频, 处理视频(获取视频信息, 压缩, 合并, 切片, 截屏等)操作
*/
class videoExt
{

    /**
     * 断点下载远程文件
     * @param string $remote_file 远程文件url, 如 http://video.sanhao.com/video/opencourse/204/204.mp4
     * @param string $local_dir 本地路径, 如 /usr/share/nginx/html/php_services/data/video_slice/
     * @param string $filename 文件名, 如 212.mp4
     * @return bool
     * @throws Exception
     */
    public function download($remote_file, $local_dir, $filename)
    {
        if (!file_exists($local_dir)) {
            mkdir($local_dir, 0777, true);
        }
        try {
            $remote_file_pointer = fopen($remote_file, 'rb');
            $local_file_pointer = fopen($local_dir . $filename, 'wb');

            while (!feof($remote_file_pointer)) {
                $tmp = fread($remote_file_pointer, 8192); // 每次下载8M
                fwrite($local_file_pointer, $tmp);
            }

            fclose($remote_file_pointer);
            fclose($local_file_pointer);
            return true;
        } catch (Exception $e) {
            throw new Exception($e->getMessage(), $e->getCode());
        }
    }

    /**
     * 获取视频长度,单位为秒
     * @param string $filename 视频文件的绝对路径, 如/usr/share/nginx/html/data/video_slice/212.mp4
     * @return int $time
     */
    public function get_duration($filename)
    {
        $cmd = 'ffmpeg -i ' . $filename . ' 2>&1 | grep \'Duration\' | cut -d \' \' -f 4 | sed s/,//';
        $content = exec($cmd);
        if (!$content || $content == '') return 0;
        $tmp = explode(':', $content);
        $time = $tmp[0] * 3600 + $tmp[1] * 60 + intval($tmp[2]);
        return $time;
    }

    /**
     * 生成视频略缩图, 默认取第5秒, 返回略缩图的绝对路径
     * @param string $filename 文件的绝对路径
     * @param int $time 截取时间
     * @param string $dist_dir 缩略图的绝对存储路径
     * @return string
     */
    public function get_cover($filename, $time = 5, $dist_dir)
    {
        $file_info = pathinfo($filename);
        $cover_file = $dist_dir . $file_info['filename'] . '.jpg';
        exec("ffmpeg -i " . $filename . " -y -f mjpeg -ss " . $time . " -t 0.001 " . $cover_file . "");
        return $cover_file;
    }

    /**
     * 压缩视频, 减少视频体积
     * @param string $filename 文件的绝对路径
     * @param string $new_filename 压缩文件的绝对路径
     */
    public function compress($filename, $new_filename)
    {
        $cmd = 'ffmpeg -i ' . $filename . ' -c:v libx264 -crf 18 ' . $new_filename;
        exec($cmd);
    }

    /**
     * 视频切片, 默认切片大小为5秒, 返回m3u8文件的绝对路径
     * @param string $filename 文件的绝对路径
     * @param int $interval 切片长度(s)
     * @param string $remote_url 远程访问地址, 只到目录层,
     * 如完整路径为       /usr/dev/record/204/204-001.ts
     * 那么$remote_url为 http://yourdomain/dev/record/204/
     * @param string $dist_dir 本地存储ts文件和m3u8文件的绝对路径
     * @param int $duration 总切片长度,单位秒
     * @return array [cmd命令,生成的m3u8文件的绝对路径]
     */
    public function m3u8($filename, $interval = 5, $remote_url, $dist_dir, $duration = 0)
    {
        $file_info = pathinfo($filename);
        $m3u8_file = $dist_dir . $file_info['filename'] . '.m3u8';
        $cmd = 'ffmpeg ';
        if ($duration > 0) {
            $time = $this->seconds2time($duration);
            $cmd .= '-ss 0 -t ' . $time . ' ';
        }
        $cmd .= '-i ' . $filename . ' -c copy -map 0  -f segment -segment_list ' . $m3u8_file;
        $cmd .= ' -segment_time ' . $interval . ' -segment_list_entry_prefix ' . $remote_url . ' ';
        $cmd .= $dist_dir . $file_info['filename'] . '-%03d.ts';
        $rs = exec($cmd);
        return [$cmd,$m3u8_file];
    }


    /**
     * 把秒数转换为时分秒的格式
     * @param int $times 秒数
     * @return string 时分秒字符串
     */
    public function seconds2time($times)
    {
        $result = '00:00:00';
        if ($times > 0) {
            $hour = floor($times / 3600);
            $minute = floor(($times - 3600 * $hour) / 60);
            $second = floor((($times - 3600 * $hour) - 60 * $minute) % 60);
            $result = $hour . ':' . $minute . ':' . $second;
        }
        return $result;
    }
}
